home *** CD-ROM | disk | FTP | other *** search
/ The AGA Experience 3 / AGA Experience Volume 3 (1997)(NFA - SAdENESS)[!].iso / software / utilities / misc / atebeta5b / source-code / atmbeta1a.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-25  |  38.7 KB  |  1,191 lines

  1. /* Adobe Type Manager BETA 1.0 for the Amiga
  2.    Perpetrated by OPTIMUS PRIME, AUTOBOT Commander
  3.    (Also known as Gordon Fecyk)
  4.  
  5.    This BETA source code may NOT be disributed or altered.
  6.    Liabilities: If anything bad happens to your computer I'm not responsible.
  7.    So there.  Thphth.
  8.  
  9.    Source is specific for DICE C 3.0 for the Amiga.  Requires
  10.    postlib.h and post.library 1.7 by Adrian Ayward.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #include <exec/types.h>
  17. #include <exec/exec.h>
  18. #include <exec/libraries.h>
  19. #include <clib/exec_protos.h>
  20. #include <dos/dos.h>
  21. #include <graphics/rastport.h>
  22. #include <graphics/text.h>
  23. #include <diskfont/diskfont.h>
  24. #include "postlib.h"
  25.  
  26. /* Set to 1 for printing PostScript debugging messages */
  27. #define OPTTRACE 0
  28. #define OPTDEBUG 0
  29.  
  30. /* PostScript external data */
  31. struct    Library        *PSbase;        /* Library struct for post.library */
  32. struct    PSparm        psParm;            /* For some stupid reason this needs */
  33.                         /* to be external.  Thanks Adrian. */
  34.     int        psActivation;        /* Record for PS activation */
  35.     int        psError;        /* Error checking for each PS call */
  36.     APTR        functionTable[10];    /* Table of external fcns for POST */
  37.     char        nameBuffer[100 + 5];    /* Bogus space for PS initalization */
  38.  
  39.     /* Functions called by POST use these pointers */
  40.     int        *charPosX, *charPosY;
  41.     int        *lowLeftX, *lowLeftY, *upRightX, *upRightY;
  42. /* end of PostScript external data (I hope) */
  43.  
  44. /* External pointers for system patches */
  45. struct    Library        *diskfontBase;
  46. struct    Library        *gfxBase;
  47.  
  48. /* FontNode struct, holds all data specific to a built TextFont */
  49. struct    FontNode {
  50.     /* basic Node struct for searches */
  51.     struct    Node        fn_Node;
  52.     /* format for fn_Name: "%50s / %5d / %2x" for "name / size / style" */
  53.     /* fn_Name is mainly used for node searching */
  54.         char        fn_Name[64];
  55.     /* Set to non-zero if a certain character exists already */
  56.         char        fn_BuiltChars[256];
  57.     /* Data POST uses */
  58.         int        fn_LowChar, fn_HighChar;
  59.         int        fn_OptBaseLine, fn_BaseLine;
  60.         int        fn_NominalWidth, fn_NominalCount;
  61.         char        fn_OptFontEncoding, fn_TypefaceName[64];
  62.         int        fn_MaxFontLength, fn_MaxCharLength;
  63.         int        fn_MaxModulo, fn_MaxWidth, fn_ActWidth;
  64.         int        fn_NomCount, fn_NomWidth;
  65.         int        fn_BaseLength, fn_FontSize;
  66.         UBYTE        fn_Style;
  67.     /* Bounding box & graphic position info */
  68.         int        fn_LowLeftX[256], fn_LowLeftY[256];
  69.         int        fn_UpRightX[256], fn_UpRightY[256];
  70.         int        fn_CharPosX, fn_CharPosY;
  71.     /* Pointers to data areas in the TextFont struct */
  72.         char        *fn_CharData, *fn_CharFontName;
  73.         short        *fn_CharLoc, *fn_CharSpace, *fn_CharKern;
  74.     /* The TextFont in question */
  75.     struct    TextFont    *fn_TextFont;
  76.     };
  77.  
  78. /* modes for fn_BuiltChars */
  79. #define    CHAR_NOT_DRAWN    0
  80. #define    CHAR_DRAWN    2
  81. #define    CHAR_NEEDED    1
  82.  
  83. /* Message structures, all based on my extended Message struct ATMMessage */
  84. struct    ATMMessage {
  85.     struct    Message        atm_Message;
  86.         int        atm_MsgLength;
  87.         char        *atm_DestPort;
  88.     };
  89.  
  90. struct    DiskfontMsg {
  91.     struct    ATMMessage    df_ATMMsg;
  92.     struct    TextAttr    *df_TextAttr;
  93.     struct    TextFont    *df_TextFont;
  94.         BOOL        df_ATMFont;
  95.     };
  96.  
  97. struct    TextMsg {
  98.     struct    ATMMessage    tm_ATMMsg;
  99.     struct    RastPort    *tm_RastPort;
  100.         STRPTR        tm_Chars;
  101.         WORD        tm_Length;
  102.         BOOL        tm_ATMFont;
  103.     };
  104.  
  105. struct    SSStyleMsg {
  106.     struct    ATMMessage    ss_ATMMsg;
  107.     struct    RastPort    *ss_RastPort;
  108.         ULONG        ss_NewStyle;
  109.         ULONG        ss_Enable;
  110.     struct    TextFont    *ss_ChangedFont;
  111.         ULONG        ss_SoftStyleNeeded;
  112.         BOOL        ss_ATMFont;
  113.     };
  114.  
  115. /* Prototypes of system patches and original functions */
  116. __geta4 __regargs struct TextFont    *NewOpenDiskFont(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase);
  117. __geta4          struct TextFont    *(*OldOpenDiskFont)(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase);
  118. __geta4    __regargs     void        NewText(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase);
  119. __geta4               void        (*OldText)(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase);
  120. __geta4    __regargs     ULONG        NewSSStyle(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase);
  121. __geta4             ULONG        (*OldSSStyle)(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase);
  122. /* Message sender for the above three patches */
  123. __geta4               BOOL        ATMSendMsg(struct ATMMessage *atmMsg);
  124.  
  125. /* Prototypes of external functions that POST will use */
  126. __geta4    void        SetBBox(int aChar, int leftX, int leftY, int rightX, int rightY);
  127. __geta4    void        SetCPos(int charPosX, int charPosY);
  128. __geta4    void        SigInt(void);
  129.  
  130. /* Functions for the PostScript interface and tracing */
  131.     void        PSTrace(char *format, ...);
  132.     void        PSIntf(char *format, ...);
  133.  
  134. /* Functions to simplify some loops, these do most of the PostScript gruntwork */
  135. struct    TextFont    *MakeATMFont(struct FontNode *fontNode, struct TextAttr *textAttr);
  136.     BOOL        MakeATMChars(struct FontNode *fontNode);
  137.  
  138. /* Functions from older versions of ATMServer (with a new one: AddATMStyle) */
  139.     void        chkabort(void) { return; };    /* Kill CTRL-C handler */
  140.     void        ClearFontNames(struct List *fontList);
  141.     BOOL        AddATMFont(struct List *fontList, struct DiskfontMsg *diskfontMsg);
  142.     BOOL        AddATMStyle(struct List *fontList, struct SSStyleMsg *sssMsg);
  143.     BOOL        AddATMChars(struct List *fontList, struct TextMsg *textMsg);
  144.  
  145. /* Mainline of code */
  146. int main()
  147. {
  148.     APTR        oldFuncPtr, newFuncPtr = &NewOpenDiskFont;
  149.     APTR        oldTextPtr, newTextPtr = &NewText;
  150.     APTR        oldSSSPtr, newSSSPtr = &NewSSStyle;
  151.     char        *versionInfo = "$VER:  AdobeTypeManager_BETA 1.0 for the Amiga (01.4.95)";
  152. struct    List        *fontList;
  153. struct    DiskfontMsg    *diskfontMsg;
  154. struct    TextMsg        *textMsg;
  155. struct    SSStyleMsg    *sssMsg;
  156. struct    MsgPort        *atmODFPort, *atmTextPort, *atmSSSPort;
  157.     ULONG        signal, odfSig, textSig, sssSig, breakSig = SIGBREAKF_CTRL_C;
  158.     BOOL        keepGoing = TRUE;
  159.  
  160.     /* Do as much allocating as practical then check for failures */
  161.         /* Message ports */
  162.     atmODFPort = CreateMsgPort();
  163.     atmTextPort = CreateMsgPort();
  164.     atmSSSPort = CreateMsgPort();
  165.         /* ATM font list */
  166.     fontList = (struct List *)AllocMem(sizeof(struct List ), MEMF_CLEAR);
  167.         /* post.library (minimum V15) */
  168.     PSbase = OpenLibrary("post.library", 15L);
  169.         /* graphics and diskfont libraries (mininum V36) */
  170.     diskfontBase = OpenLibrary("diskfont.library", 36L);
  171.     gfxBase = OpenLibrary("graphics.library", 36L);
  172.  
  173.     /* check for failures */
  174.     if (atmODFPort == 0 || atmTextPort == 0 || atmSSSPort == 0 || PSbase == 0 || gfxBase == 0 || diskfontBase == 0 || fontList == 0)
  175.     {
  176.         if (atmSSSPort != 0)
  177.             DeleteMsgPort(atmSSSPort);
  178.         else
  179.             printf("Error opening one message port\n");
  180.         if (atmODFPort != 0)
  181.             DeleteMsgPort(atmODFPort);
  182.         else
  183.             printf("Error opening one message port\n");
  184.         if (atmTextPort != 0)
  185.             DeleteMsgPort(atmTextPort);
  186.         else
  187.             printf("Error opening one message port\n");
  188.         if (PSbase != 0)
  189.             CloseLibrary(PSbase);
  190.         else
  191.             printf("Error opening post.library\n");
  192.         if (fontList != 0)
  193.             FreeMem(fontList, sizeof(struct List));
  194.         else
  195.             printf("Error allocating RAM for fontList\n");
  196.         if (gfxBase != 0)
  197.             CloseLibrary(gfxBase);
  198.         else
  199.             printf("Error opening graphics.library\n");
  200.         if (diskfontBase != 0)
  201.             CloseLibrary(diskfontBase);
  202.         else
  203.             printf("Error opening diskfont.library\n");
  204.     }
  205.  
  206.     /* initalize the PostScript activation */
  207.     PSTrace("%%Initalizing PostScript Activation\n");
  208.     psParm.page.buf[0] = nameBuffer;
  209.     psParm.page.len = 100;
  210.     psParm.page.depth = 1;
  211.     psParm.page.xoff = 0;
  212.     psParm.page.yoff = 0;
  213.     psParm.page.xbytes = 10;
  214.     psParm.page.xsize = 80;
  215.     psParm.page.ysize = 10;
  216.     psParm.page.ybase = 0;
  217.     psParm.page.xden = 72;
  218.     psParm.page.yden = 72;
  219.     psParm.page.ydir = -1;
  220.     psParm.memvlen = 20000;
  221.     psParm.memflen = 10000;
  222.     psParm.memllen = defmemllen;
  223.     psParm.memhlen = minmemhlen;
  224.     psParm.infh = Input();
  225.     psParm.outfh = Output();
  226.     psParm.errfh = Output();
  227.     psParm.funcmax = 2;
  228.     functionTable[0] = &SetBBox;
  229.     functionTable[1] = &SetCPos;
  230.     psParm.functab = functionTable;
  231.     psParm.userdata = 0;
  232.     psParm.flushfunc = 0;
  233.     psParm.copyfunc = 0;
  234.     psParm.reserved[0] = 0;
  235.     psParm.reserved[1] = 0;
  236.  
  237.     psActivation = PScreateact(&psParm);
  238.     if (psActivation <= errmax)
  239.     {
  240.         printf("PostScript activation failed\n");
  241.         DeleteMsgPort(atmODFPort);
  242.         DeleteMsgPort(atmTextPort);
  243.         DeleteMsgPort(atmSSSPort);
  244.         FreeMem(fontList, sizeof(struct List));
  245.         CloseLibrary(PSbase);
  246.         CloseLibrary(gfxBase);
  247.         CloseLibrary(diskfontBase);
  248.         return(20);
  249.     }
  250.  
  251.     /* Run ATM startup files */
  252.     PSTrace("%%All initalization passed, running PS startup & encoding files\n");
  253.     PSIntf("(%.100s) run clear\n", "PSFonts:ATMinit.ps");
  254.     PSIntf("/encoding StandardEncoding 256 array copy def\n");
  255.     PSIntf("[ (%.100s) run] aload length 2 idiv\n", "PSFonts:ATMEncoding.ps");
  256.     PSIntf("{ encoding 3 1 roll put } repeat\n");
  257.  
  258.     /* Setup ports and list */
  259.     atmODFPort->mp_Node.ln_Name = "ATM_ODF_Port";
  260.     atmTextPort->mp_Node.ln_Name = "ATM_Text_Port";
  261.     atmSSSPort->mp_Node.ln_Name = "ATM_SSS_Port";
  262.     odfSig = 1 << atmODFPort->mp_SigBit;
  263.     textSig = 1 << atmTextPort->mp_SigBit;
  264.     sssSig = 1 << atmSSSPort->mp_SigBit;
  265.     atmODFPort->mp_Node.ln_Pri = 0;
  266.     atmTextPort->mp_Node.ln_Pri = 0;
  267.     atmSSSPort->mp_Node.ln_Pri = 0;
  268.     AddPort(atmODFPort);
  269.     AddPort(atmTextPort);
  270.     AddPort(atmSSSPort);
  271.     fontList->lh_Type = NT_USER;
  272.     NewList(fontList);
  273.     printf("ATM BETA 1.0 ready.  Press CTRL-C to exit.\n");
  274.  
  275.     /* Perform patches */
  276.     Forbid();
  277.     oldFuncPtr = SetFunction(diskfontBase, -0x1E, newFuncPtr);
  278.     OldOpenDiskFont = oldFuncPtr;
  279.     oldTextPtr = SetFunction(gfxBase, -0x3C, newTextPtr);
  280.     OldText = oldTextPtr;
  281.     oldSSSPtr = SetFunction(gfxBase, -0x5A, newSSSPtr);
  282.     OldSSStyle = oldSSSPtr;
  283.     Permit();
  284.     /* I got the offsets from the included pragmas files. */
  285.  
  286.     /* Begin main process loop */
  287.     for (;;)
  288.     {
  289.         signal = Wait (breakSig | textSig | odfSig | sssSig);
  290.  
  291.         if ((signal & breakSig) || (keepGoing == FALSE))
  292.         {
  293.             /* Clear out all ports */
  294.             while (diskfontMsg = (struct DiskfontMsg *)GetMsg(atmODFPort))
  295.             {
  296.                 diskfontMsg->df_ATMFont = FALSE;
  297.                 ReplyMsg((struct Message *)diskfontMsg);
  298.             }
  299.             RemPort(atmODFPort);
  300.             while (textMsg = (struct textMsg *)GetMsg(atmTextPort))
  301.             {
  302.                 textMsg->tm_ATMFont = FALSE;
  303.                 ReplyMsg((struct Message *)textMsg);
  304.             }
  305.             RemPort(atmTextPort);
  306.             while (sssMsg = (struct sssMsg *)GetMsg(atmSSSPort))
  307.             {
  308.                 sssMsg->ss_ATMFont = FALSE;
  309.                 ReplyMsg((struct Message *)sssMsg);
  310.             }
  311.             RemPort(atmSSSPort);
  312.             keepGoing = FALSE;
  313.             break;
  314.         }
  315.         if ((signal & textSig) && (keepGoing == TRUE))
  316.         {
  317.             while (textMsg = (struct TextMsg *)GetMsg(atmTextPort))
  318.             {
  319.                 keepGoing = AddATMChars(fontList, textMsg);
  320.                 if (keepGoing == FALSE)
  321.                     PSTrace("%%Out of memory or some other error drawing new chars\n");
  322.                 ReplyMsg((struct Message *)textMsg);
  323.             }
  324.         }
  325.         if ((signal & odfSig) && (keepGoing == TRUE))
  326.         {
  327.             while (diskfontMsg = (struct DiskfontMsg *)GetMsg(atmODFPort))
  328.             {
  329.                 keepGoing = AddATMFont(fontList, diskfontMsg);
  330.                 if (keepGoing == FALSE)
  331.                     PSTrace("%%Out of memory creating new textfont\n");
  332.                 ReplyMsg((struct Message *)diskfontMsg);
  333.             }
  334.         }
  335.         if ((signal & sssSig) && (keepGoing == TRUE))
  336.         {
  337.             while (sssMsg = (struct SSStyleMsg *)GetMsg(atmSSSPort))
  338.             {
  339.                 keepGoing = AddATMStyle(fontList, sssMsg);
  340.                 if (keepGoing == FALSE)
  341.                     PSTrace("%%Out of memory creating new textfont for new style\n");
  342.                 ReplyMsg((struct Message *)sssMsg);
  343.             }
  344.         }
  345.     }
  346.  
  347.     /* Clean up time */
  348.     Forbid();
  349.     newFuncPtr = SetFunction(diskfontBase, -0x1E, oldFuncPtr);
  350.     newTextPtr = SetFunction(gfxBase, -0x3C, oldTextPtr);
  351.     newSSSPtr = SetFunction(gfxBase, -0x5A, oldSSSPtr);
  352.     Permit();
  353.     /* Allow user to close applications that use ATM fonts */
  354.     printf("Patches removed, press CTRL-C again to exit\n");
  355.     Wait(breakSig);
  356.     DeleteMsgPort(atmODFPort);
  357.     DeleteMsgPort(atmTextPort);
  358.     DeleteMsgPort(atmSSSPort);
  359.     ClearFontNames(fontList);
  360.     FreeMem(fontList, sizeof(struct List));
  361.     PSdeleteact(psActivation);
  362.     CloseLibrary(PSbase);
  363.  
  364.     printf("Now exiting.  Remember: This is BETA software!  Use at own risk!\n");
  365.     return(0);
  366. }
  367.  
  368. void ClearFontNames(struct List *fontList)
  369. {
  370. struct    FontNode    *workNode, *nextNode;
  371.  
  372.     workNode = (struct FontNode *)(fontList->lh_Head);
  373.     while (nextNode = (struct FontNode *)(workNode->fn_Node.ln_Succ))
  374.     {
  375.         RemFont(workNode->fn_TextFont);
  376.         FreeMem(workNode->fn_TextFont, workNode->fn_MaxFontLength + 64);
  377.         FreeMem(workNode, sizeof(struct FontNode));
  378.         workNode = nextNode;
  379.     }
  380.     return;
  381. }
  382.  
  383. BOOL AddATMChars(struct List *fontList, struct TextMsg *textMsg)
  384. {
  385. struct    FontNode    *fontNode;
  386.     char        *fontName, *builtChars, nodeName[64];
  387.     STRPTR        oneChar;
  388.     UWORD        fontSize;
  389.     UBYTE        fontStyle, indexY;
  390.     BOOL        callMakeATMChars = FALSE;
  391.     BOOL        addATMCharsOK;
  392.     WORD        indexX, length;
  393.  
  394.     fontName = textMsg->tm_RastPort->Font->tf_Message.mn_Node.ln_Name;
  395.     fontSize = textMsg->tm_RastPort->Font->tf_YSize;
  396.     fontStyle = (textMsg->tm_RastPort->Font->tf_Style) & (FSF_BOLD | FSF_ITALIC);
  397.     /* NOTE: ATM can only worry about substituting bold or italic versions, */
  398.     /*       setting soft styles will take care of underlining */
  399.  
  400.     sprintf(nodeName, "%50s / %5d / %2x", fontName, fontSize, fontStyle);
  401.     fontNode = (struct FontNode *)FindName(fontList, nodeName);
  402.  
  403.     /* If the desired style isn't found try finding the plain style */
  404.     if (fontNode == 0)
  405.     {
  406.         fontStyle = FS_NORMAL;
  407.         sprintf(nodeName, "%50s / %5d / %2x", fontName, fontSize, fontStyle);
  408.         fontNode = (struct FontNode *)FindName(fontList, nodeName);
  409.     }
  410.  
  411.     if (fontNode != 0)
  412.     {
  413.         /* begin pre-scan, determine what chars really need to be drawn */
  414.         length = textMsg->tm_Length;
  415.         builtChars = fontNode->fn_BuiltChars;
  416.         oneChar = (textMsg->tm_Chars);
  417.         for (indexX = 0; indexX < length; indexX++)
  418.         {
  419.             /* Mark needed characters */
  420.             indexY = oneChar[indexX];
  421.             if (builtChars[indexY] == CHAR_NOT_DRAWN)
  422.             {
  423.                 builtChars[indexY] = CHAR_NEEDED;
  424.                 callMakeATMChars = TRUE;
  425.             }
  426.         }
  427.         textMsg->tm_ATMFont = TRUE;
  428.         addATMCharsOK = TRUE;
  429.         if (callMakeATMChars == TRUE)
  430.         {
  431.             addATMCharsOK = MakeATMChars(fontNode);
  432.         }
  433.     }
  434.     else
  435.     {
  436.         textMsg->tm_ATMFont = FALSE;
  437.         addATMCharsOK = TRUE;
  438.     }
  439.  
  440.     return(addATMCharsOK);
  441. }
  442.  
  443. BOOL AddATMFont(struct List *fontList, struct DiskfontMsg *diskfontMsg)
  444. {
  445. struct    TextAttr    *textAttr;
  446. struct    FontNode    *fontNode;
  447.     UBYTE        fontStyle;
  448.     char        fontName[64], regularName[64], typefaceName[64];
  449.     char        dummyString[80], *dotPtr, optFontEncoding;
  450.     BOOL        addATMFontOK;
  451.     FILE        *atmFile;
  452.     int        lowChar, highChar;
  453.  
  454.     textAttr = diskfontMsg->df_TextAttr;
  455.     /* Make sure the font in question is an ATM font. */
  456.     strcpy(fontName, "FONTS:");
  457.     strcat(fontName, textAttr->ta_Name);
  458.     dotPtr = strchr(fontName, '.');
  459.     *dotPtr = '\0';
  460.     strcat(fontName, ".atm");
  461.     /* OK try opening the file */
  462.     atmFile = fopen(fontName, "r");
  463.     if (atmFile == 0)
  464.     {
  465.         diskfontMsg->df_ATMFont = FALSE;
  466.         return(TRUE);
  467.         /* hey, not an ATM-ready typeface so exit */
  468.     }
  469.     /* Now search to see if requested font already exists */
  470.     textAttr = diskfontMsg->df_TextAttr;
  471.     fontStyle = textAttr->ta_Style & (FSF_BOLD | FSF_ITALIC);
  472.     /* NOTE: ATM can only worry about substituting bold or italic versions, */
  473.     /*       setting soft styles will take care of underlining */
  474.  
  475.     fgets(dummyString, 79, atmFile);
  476.     sscanf(dummyString, "%c %d %d", &optFontEncoding, &lowChar, &highChar);
  477.     dotPtr = strchr(dummyString, '.');
  478.     dotPtr++;
  479.     strcpy(regularName, dotPtr);
  480.     strcpy(typefaceName, regularName);
  481.     switch(fontStyle)
  482.     {
  483.         case 0x02:
  484.             fgets(dummyString, 79, atmFile);
  485.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  486.             dotPtr = strchr(dummyString, '.');
  487.             dotPtr++;
  488.             strcpy(typefaceName, dotPtr);
  489.             break;
  490.         case 0x04:
  491.             fgets(dummyString, 79, atmFile);
  492.             fgets(dummyString, 79, atmFile);
  493.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  494.             dotPtr = strchr(dummyString, '.');
  495.             dotPtr++;
  496.             strcpy(typefaceName, dotPtr);
  497.             break;
  498.         case 0x06:
  499.             fgets(dummyString, 79, atmFile);
  500.             fgets(dummyString, 79, atmFile);
  501.             fgets(dummyString, 79, atmFile);
  502.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  503.             dotPtr = strchr(dummyString, '.');
  504.             dotPtr++;
  505.             strcpy(typefaceName, dotPtr);
  506.             break;
  507.         default:
  508.             break;
  509.     }
  510.  
  511.     fclose(atmFile);
  512.     /* If no real typeface exists for desired style, use plain style */
  513.     if (strcmp(typefaceName, regularName) == 0)
  514.         fontStyle = FS_NORMAL;
  515.  
  516.     /* Build search string and see if we don't already have this font */
  517.     sprintf(fontName, "%50s / %5d / %2x", textAttr->ta_Name, textAttr->ta_YSize, fontStyle);
  518.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  519.     if (fontNode != 0)
  520.     {
  521.         diskfontMsg->df_ATMFont = TRUE;
  522.         diskfontMsg->df_TextFont = fontNode->fn_TextFont;
  523.         return(TRUE);
  524.         /* Hey, why work if you already have results? */
  525.     }
  526.  
  527.     /* So no font node eh?  Time to make one. */
  528.     fontNode = (struct FontNode *)AllocMem(sizeof(struct FontNode), MEMF_CLEAR);
  529.     if (fontNode != 0)
  530.     {
  531.         strcpy(fontNode->fn_Name, fontName);
  532.         fontNode->fn_Node.ln_Name = fontNode->fn_Name;
  533.         fontNode->fn_Node.ln_Type = NT_USER;
  534.         fontNode->fn_Node.ln_Pri = 0;
  535.         strcpy(fontNode->fn_TypefaceName, typefaceName);
  536.         fontNode->fn_LowChar = lowChar;
  537.         fontNode->fn_HighChar = highChar;
  538.         fontNode->fn_OptFontEncoding = optFontEncoding;
  539.         fontNode->fn_Style = fontStyle;
  540.         fontNode->fn_FontSize = textAttr->ta_YSize;
  541.         fontNode->fn_TextFont = MakeATMFont(fontNode, textAttr);
  542.         if (fontNode->fn_TextFont != 0)
  543.         {
  544.             AddFont(fontNode->fn_TextFont);
  545.             diskfontMsg->df_TextFont = fontNode->fn_TextFont;
  546.             diskfontMsg->df_ATMFont = TRUE;
  547.             AddHead(fontList, (struct Node *)fontNode);
  548.             addATMFontOK = TRUE;
  549.         }
  550.         else
  551.         {
  552.             diskfontMsg->df_ATMFont = FALSE;
  553.             addATMFontOK = FALSE;
  554.             FreeMem(fontNode, sizeof(struct FontNode));
  555.         }
  556.     }
  557.     else
  558.     {
  559.         diskfontMsg->df_ATMFont = FALSE;
  560.         addATMFontOK = FALSE;
  561.     }
  562.     return(addATMFontOK);
  563. }
  564.  
  565. /* This function mimics AddATMFont except it adds fonts upon SetSoftStyle()
  566.    calls instead of OpenDiskFont() calls.  This fcn takes special
  567.    consideration of ta_Style flags. */
  568. BOOL AddATMStyle(struct List *fontList, struct SSStyleMsg *sssMsg)
  569. {
  570. struct    FontNode    *fontNode;
  571. struct    RastPort    *sssRastPort = sssMsg->ss_RastPort;
  572. struct    TextFont    *sssTextFont = sssMsg->ss_RastPort->Font;
  573. struct    TextAttr    dummyAttr;    /* For calling MakeATMFont */
  574.     char        *currentFontName, fontName[64], dummyString[80], *dotPtr;
  575.     char        typefaceName[64], regularName[64], optFontEncoding;
  576.     int        fontSize, currentStyle, desiredStyle, lowChar, highChar;
  577.     FILE        *atmFile;
  578.     BOOL        addATMStyleOK;
  579.  
  580.     currentFontName = sssRastPort->Font->tf_Message.mn_Node.ln_Name;
  581.     fontSize = sssRastPort->Font->tf_YSize;
  582.     desiredStyle = sssMsg->ss_NewStyle & sssMsg->ss_Enable;
  583.     currentStyle = desiredStyle & (FSF_BOLD | FSF_ITALIC);
  584.     /* Only pay attention to FSF_BOLD and FSF_ITALIC */
  585.     /* Build search string and see if we don't already have this font */
  586.     sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, currentStyle);
  587.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  588.     if (fontNode != 0)
  589.     {
  590.         sssMsg->ss_ATMFont = TRUE;
  591.         sssMsg->ss_ChangedFont = fontNode->fn_TextFont;
  592.         sssMsg->ss_SoftStyleNeeded = currentStyle ^ desiredStyle;
  593.         return(TRUE);
  594.         /* Hey, why work if you already have results? */
  595.     }
  596.  
  597.     /* repeat search for plain style (to avoid Intuition hangups) */
  598.     sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, FS_NORMAL);
  599.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  600.     if (fontNode == 0)
  601.     {
  602.         sssMsg->ss_ATMFont = FALSE;
  603.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  604.         return(TRUE);
  605.         /* This isn't a loaded ATM font so exit */
  606.     }
  607.  
  608.     /* OK currentStyle doesn't exist yet and it IS an ATM font.  So make it. */
  609.     
  610.     /* Make sure the font in question is an ATM font. */
  611.     strcpy(fontName, "FONTS:");
  612.     strcat(fontName, currentFontName);
  613.     dotPtr = strchr(fontName, '.');
  614.     *dotPtr = '\0';
  615.     strcat(fontName, ".atm");
  616.     /* OK try opening the file */
  617.     atmFile = fopen(fontName, "r");
  618.     if (atmFile == 0)
  619.     {
  620.         sssMsg->ss_ATMFont = FALSE;
  621.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  622.         return(TRUE);
  623.         /* hey, not an ATM-ready typeface so exit */
  624.     }
  625.  
  626.     /* Now search to see if requested typeface version exists */
  627.     fgets(dummyString, 79, atmFile);
  628.     sscanf(dummyString, "%c %d %d", &optFontEncoding, &lowChar, &highChar);
  629.     dotPtr = strchr(dummyString, '.');
  630.     dotPtr++;
  631.     strcpy(regularName, dotPtr);
  632.     strcpy(typefaceName, regularName);
  633.     switch(currentStyle)
  634.     {
  635.         case 0x02:    /* FSF_BOLD */
  636.             fgets(dummyString, 79, atmFile);
  637.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  638.             dotPtr = strchr(dummyString, '.');
  639.             dotPtr++;
  640.             strcpy(typefaceName, dotPtr);
  641.             break;
  642.         case 0x04:    /* FSF_ITALIC */
  643.             fgets(dummyString, 79, atmFile);
  644.             fgets(dummyString, 79, atmFile);
  645.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  646.             dotPtr = strchr(dummyString, '.');
  647.             dotPtr++;
  648.             strcpy(typefaceName, dotPtr);
  649.             break;
  650.         case 0x06:    /* FSF_BOLD | FSF_ITALIC */
  651.             fgets(dummyString, 79, atmFile);
  652.             fgets(dummyString, 79, atmFile);
  653.             fgets(dummyString, 79, atmFile);
  654.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  655.             dotPtr = strchr(dummyString, '.');
  656.             dotPtr++;
  657.             strcpy(typefaceName, dotPtr);
  658.             break;
  659.         default:
  660.             break;
  661.     }
  662.     fclose(atmFile);
  663.  
  664.     /* If no real typeface exists for desired style, exit */
  665.     if (strcmp(typefaceName, regularName) == 0)
  666.     {
  667.         sssMsg->ss_ATMFont = FALSE;
  668.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  669.         return(TRUE);
  670.     }
  671.  
  672.     /* OK now make a new font node for this new style */
  673.     fontNode = (struct FontNode *)AllocMem(sizeof(struct FontNode), MEMF_CLEAR);
  674.     if (fontNode != 0)
  675.     {
  676.         sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, currentStyle);
  677.         strcpy(fontNode->fn_Name, fontName);
  678.         fontNode->fn_Node.ln_Name = fontNode->fn_Name;
  679.         fontNode->fn_Node.ln_Type = NT_USER;
  680.         fontNode->fn_Node.ln_Pri = 0;
  681.         strcpy(fontNode->fn_TypefaceName, typefaceName);
  682.         fontNode->fn_LowChar = lowChar;
  683.         fontNode->fn_HighChar = highChar;
  684.         fontNode->fn_OptFontEncoding = optFontEncoding;
  685.         fontNode->fn_Style = currentStyle;
  686.         fontNode->fn_FontSize = fontSize;
  687.         dummyAttr.ta_Name = currentFontName;
  688.         dummyAttr.ta_YSize = fontSize;
  689.         dummyAttr.ta_Style = currentStyle;
  690.         dummyAttr.ta_Flags = 0;
  691.         /* Call MakeATMFont() to build this new font */
  692.         fontNode->fn_TextFont = MakeATMFont(fontNode, &dummyAttr);
  693.         if (fontNode->fn_TextFont != 0)
  694.         {
  695.             AddFont(fontNode->fn_TextFont);
  696.             sssMsg->ss_ChangedFont = fontNode->fn_TextFont;
  697.             sssMsg->ss_ATMFont = TRUE;
  698.             AddHead(fontList, (struct Node *)fontNode);
  699.             sssMsg->ss_SoftStyleNeeded = currentStyle ^ desiredStyle;
  700.             addATMStyleOK = TRUE;
  701.         }
  702.         else
  703.         {
  704.             sssMsg->ss_ATMFont = FALSE;
  705.             addATMStyleOK = FALSE;
  706.             sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  707.             FreeMem(fontNode, sizeof(struct FontNode));
  708.         }
  709.     }
  710.     else
  711.     {
  712.         sssMsg->ss_ATMFont = FALSE;
  713.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  714.         addATMStyleOK = FALSE;
  715.     }
  716.     return(addATMStyleOK);
  717. }
  718.  
  719. /* Here we build a new TextFont */
  720. struct TextFont *MakeATMFont(struct FontNode *fontNode, struct TextAttr *textAttr)
  721. {
  722. struct    TextFont    *newFont;
  723.     int        zZ, z1, z2, index, y1, y2;
  724.  
  725.     /* Since AddATMFont() did all the checking for this fcn, just start rendering */
  726.     PSTrace("%%Loading typeface %s\n", fontNode->fn_TypefaceName);
  727.     PSIntf("/fontname /%.100s def\n", fontNode->fn_TypefaceName);
  728.     PSIntf("fontname findfont pop\n");
  729.     PSIntf("/font fontname .findfont def\n");
  730.     PSTrace("%%Encoding font\n");
  731.     PSIntf("/newfont font maxlength dict def\n");
  732.     PSIntf(    "font\n"
  733.         "{ exch dup /FID ne"
  734.         "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n"
  735.         "forall\n");
  736.     if (fontNode->fn_OptFontEncoding == 'S')
  737.         PSIntf("newfont /Encoding encoding put\n");
  738.     PSIntf("/_.100s newfont definefont pop\n", fontNode->fn_TypefaceName);
  739.     if (psError != 0)
  740.     {
  741.         PSTrace("%%PostScript error encoding typeface\n");
  742.         psError = -1;
  743.         return(0);
  744.     }
  745.  
  746.     /* Prepare external ptrs for BBox generation and start generating */
  747.     lowLeftX = fontNode->fn_LowLeftX;
  748.     lowLeftY = fontNode->fn_LowLeftY;
  749.     upRightX = fontNode->fn_UpRightX;
  750.     upRightY = fontNode->fn_UpRightY;
  751.     PSTrace("%%Generating Bounding Boxes\n");
  752.     PSIntf("/cstr 1 string def\n");
  753.     PSIntf("newfont 1000 scalefont setfont\n");
  754.     PSIntf(    "%d 1 %d\n"
  755.         "{ /i exch def cstr 0 i put null i\n"
  756.         "  0 0 moveto cstr false charpath pathbbox newpath\n"
  757.         "  4 { round cvi 4 1 roll } repeat\n"
  758.         "  5 0 callextfunc\n"
  759.         "} for\n", fontNode->fn_LowChar, fontNode->fn_HighChar);
  760.     if (psError != 0)
  761.     {    
  762.         PSTrace("%%PostScript error generating bounding boxes\n");
  763.         psError = -1;
  764.         return(0);
  765.     }
  766.  
  767.     /* Start generating baseline info from BBox info */
  768.     zZ = 1000;    /* Formerly zZ = (1000 * 72) / optYDen */
  769.     z1 = z2 = 0;
  770.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index++)
  771.     {
  772.         if (fontNode->fn_LowLeftY[index] < z1)
  773.             z1 = fontNode->fn_LowLeftY[index];
  774.         if (fontNode->fn_UpRightY[index] > z2)
  775.             z2 = fontNode->fn_UpRightY[index];
  776.     }
  777.     if (z2 == z1)
  778.     {
  779.         PSTrace("%%All chars in this typeface are null!\n");
  780.         psError = -1;
  781.         return(0);
  782.     }
  783.     fontNode->fn_OptBaseLine = (1000 * (-z1) + (z2 - z1) / 2) / (z2 - z1);
  784.     if ((z2 - z1 > zZ) && fontNode->fn_OptFontEncoding == 'S')
  785.     {
  786.         y1 = y2 = 0;
  787.         for (index = 'A'; index <= 'Z'; index++)
  788.         {
  789.             if (fontNode->fn_LowLeftY[index] < y1)
  790.                 y1 = fontNode->fn_LowLeftY[index];
  791.             if (fontNode->fn_UpRightY[index] > y2)
  792.                 y2 = fontNode->fn_UpRightY[index];
  793.         }
  794.         for (index = 'a'; index <= 'z'; index++)
  795.         {
  796.             if (fontNode->fn_LowLeftY[index] < y1)
  797.                 y1 = fontNode->fn_LowLeftY[index];
  798.             if (fontNode->fn_UpRightY[index] > y2)
  799.                 y2 = fontNode->fn_UpRightY[index];
  800.         }
  801.         if (y2 - y1 <= zZ)
  802.             fontNode->fn_OptBaseLine = (1000 * (-y1) + zZ / 2) / zZ;
  803.         else
  804.             fontNode->fn_OptBaseLine = (1000 * (-y1) + (y2 - y1) / 2) / (y2 - y1);
  805.     }
  806.     PSTrace("%%Baseline set to %d/1000 of pixel height\n", fontNode->fn_OptBaseLine);
  807.  
  808.     /* Prepare memory space for the new font */
  809.     PSTrace("%%Allocating space for new TextFont\n");
  810.     fontNode->fn_BaseLength = sizeof(struct TextFont) + 8 * (fontNode->fn_HighChar - fontNode->fn_LowChar + 2);
  811.     fontNode->fn_MaxWidth = 0;
  812.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index++)
  813.         fontNode->fn_MaxWidth += ((fontNode->fn_UpRightX[index] - fontNode->fn_LowLeftX[index]) * fontNode->fn_FontSize) / 1000 + 2;
  814.     fontNode->fn_MaxModulo = ((fontNode->fn_MaxWidth + 15) >> 3) & ~1;
  815.     fontNode->fn_MaxCharLength = fontNode->fn_MaxModulo * fontNode->fn_FontSize;
  816.     fontNode->fn_MaxFontLength = fontNode->fn_BaseLength + fontNode->fn_MaxCharLength + 2 + 76;
  817.  
  818.     newFont = (struct TextFont *)AllocMem((fontNode->fn_MaxFontLength + 64), (MEMF_PUBLIC | MEMF_CLEAR | MEMF_CHIP));
  819.     if (newFont == 0)
  820.     {
  821.         PSTrace("%%Cannot get memory for new TextFont\n");
  822.         psError = -1;
  823.         return(0);
  824.     }
  825.     fontNode->fn_CharLoc =        (short *)&newFont[1];
  826.     fontNode->fn_CharSpace =     (short *)&fontNode->fn_CharLoc[(fontNode->fn_HighChar - fontNode->fn_LowChar + 2) * 2];
  827.     fontNode->fn_CharKern =        (short *)&fontNode->fn_CharSpace[fontNode->fn_HighChar - fontNode->fn_LowChar + 2];
  828.     fontNode->fn_CharData =     (char  *)&fontNode->fn_CharKern[fontNode->fn_HighChar - fontNode->fn_LowChar + 2];
  829.     fontNode->fn_CharFontName =     (char  *)&fontNode->fn_CharData[fontNode->fn_MaxCharLength];
  830.     strcpy(fontNode->fn_CharFontName, textAttr->ta_Name);
  831.     PSTrace("TextFont pointers:   Font at    %8X\n", newFont);
  832.     PSTrace("                     Loc at     %8X\n", fontNode->fn_CharLoc);
  833.     PSTrace("                     Space at   %8X\n", fontNode->fn_CharSpace);
  834.     PSTrace("                     Kern at    %8X\n", fontNode->fn_CharKern);
  835.     PSTrace("                     Data at    %8X\n", fontNode->fn_CharData);
  836.     PSTrace("                     Name at    %8X\n", fontNode->fn_CharFontName);
  837.     PSTrace("                     Name is %s\n", fontNode->fn_CharFontName);
  838.  
  839.     /* Prepare remaining TextFont attributes */
  840.     newFont->tf_Message.mn_Node.ln_Name = fontNode->fn_CharFontName;
  841.     newFont->tf_Message.mn_Node.ln_Type = NT_FONT;
  842.     newFont->tf_Message.mn_Length = fontNode->fn_MaxFontLength + 64;
  843.     newFont->tf_YSize = textAttr->ta_YSize;
  844.     newFont->tf_Style = fontNode->fn_Style;
  845.     newFont->tf_Flags = (FPF_ROMFONT | FPF_PROPORTIONAL | FPF_DESIGNED);
  846.     fontNode->fn_BaseLine = (textAttr->ta_YSize * fontNode->fn_OptBaseLine + 500) / 1000;
  847.     if (fontNode->fn_BaseLine < 0)
  848.         fontNode->fn_BaseLine = 0;
  849.     if (fontNode->fn_BaseLine > textAttr->ta_YSize)
  850.         fontNode->fn_BaseLine = textAttr->ta_YSize - 1;
  851.     newFont->tf_Baseline = textAttr->ta_YSize - fontNode->fn_BaseLine - 1;
  852.     newFont->tf_BoldSmear = textAttr->ta_YSize / 20 + 1;
  853.     newFont->tf_LoChar = fontNode->fn_LowChar;
  854.     newFont->tf_HiChar = fontNode->fn_HighChar;
  855.     newFont->tf_Modulo = fontNode->fn_MaxModulo;
  856.     newFont->tf_CharLoc = (APTR)fontNode->fn_CharLoc;
  857.     newFont->tf_CharSpace = (APTR)fontNode->fn_CharSpace;
  858.     newFont->tf_CharKern = (APTR)fontNode->fn_CharKern;
  859.     newFont->tf_CharData = (APTR)fontNode->fn_CharData;
  860.  
  861.     /* Prepare additional values in fontNode struct */
  862.     fontNode->fn_ActWidth = 0;
  863.     fontNode->fn_NomWidth = 0;
  864.     fontNode->fn_NomCount = 0;
  865.     fontNode->fn_CharPosX = 0;
  866.     /* Right here should be the end of MakeATMFont() except for tf_CharSpace */
  867.     /* and tf_CharKern array generation.  The rest will move to MakeATMChars() */
  868.  
  869.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index ++)
  870.     {
  871.         z1 = (fontNode->fn_LowLeftX[index] * fontNode->fn_FontSize * 72 - 41000) / 72000;
  872.         z2 = (fontNode->fn_UpRightX[index] * fontNode->fn_FontSize * 72 + 41000) / 72000;
  873. //        if (z1 < 0)
  874. //            z1 = 0;
  875.         zZ = z2 - z1;
  876. //        fontNode->fn_CharPosX += zZ;
  877.         fontNode->fn_CharLoc[(index - fontNode->fn_LowChar) * 2 + 1] = zZ;
  878.         fontNode->fn_CharSpace[(index - fontNode->fn_LowChar)] = zZ + 1;
  879.         fontNode->fn_CharKern[(index - fontNode->fn_LowChar)] = z1;
  880.         fontNode->fn_ActWidth += zZ;
  881.         if (fontNode->fn_LowLeftY[index] != fontNode->fn_UpRightY[index])
  882.         {
  883.             fontNode->fn_NomWidth += zZ;
  884. //            fontNode->fn_NomWidth += (z1 + zZ);
  885.             fontNode->fn_NomCount++;
  886.         }
  887.     }
  888.  
  889.     /* Some extra parts of the TextFont struct missed above */
  890.     newFont->tf_XSize = fontNode->fn_NomWidth / (fontNode->fn_HighChar - fontNode->fn_LowChar);
  891.     /* Reset position ptr for char drawing */
  892.     fontNode->fn_ActWidth = 0;
  893.     /* OK, finally the new TextFont is ready for use (maybe...) */
  894.     if (psError != 0)
  895.     {
  896.         FreeMem(newFont, fontNode->fn_MaxFontLength + 64);
  897.         return(0);
  898.     }
  899.     return(newFont);        
  900. }
  901.  
  902. /* MakeATMChars() searches fn_BuiltChars and builds characters flagged with */
  903. /* CHAR_NEEDED, then sets the value to CHAR_DRAWN.  */
  904. BOOL MakeATMChars(struct FontNode *fontNode)
  905. {
  906.     int        index, y1, y2, z1, z2, zZ;
  907. struct    TextFont    *newFont = fontNode->fn_TextFont;
  908.  
  909.     /* Beginning of MakeATMChars() (Fingers crossed) */
  910.     /* Prepare page area for the new chars */
  911.     psParm.page.buf[0] = newFont->tf_CharData;
  912.     psParm.page.len = fontNode->fn_MaxCharLength;
  913.     psParm.page.depth = 1;
  914.     psParm.page.xoff = 0;
  915.     psParm.page.yoff = 0;
  916.     psParm.page.xbytes = fontNode->fn_MaxModulo;
  917.     psParm.page.xsize = fontNode->fn_MaxWidth;
  918.     psParm.page.ysize = fontNode->fn_FontSize;
  919.     psParm.page.ybase = 0;
  920.     psParm.page.yheight = fontNode->fn_FontSize;
  921.     /* For a silly reason I can't have multiple page descriptions. Thanks Adrian. */
  922.     PSsetdevice(psActivation, &psParm.page);
  923.     /* Prepare external pointers charPosX and Y */
  924.     charPosX = &fontNode->fn_CharPosY;
  925.     charPosY = &fontNode->fn_CharPosY;
  926.  
  927.     /* OK, draw some characters.  NOTE: I will move actual drawing to */
  928.     /* the MakeATMChars() fcn.  This is NOT permament. */
  929.     PSTrace("%%Rendering characters\n");
  930.     /* first re-load the typeface needed... */
  931.     PSIntf("/fontname /%.100s def\n", fontNode->fn_TypefaceName);
  932.     PSIntf("fontname findfont pop\n");
  933.     PSIntf("/font fontname .findfont def\n");
  934.     PSTrace("%%Encoding font\n");
  935.     PSIntf("/newfont font maxlength dict def\n");
  936.     PSIntf(    "font\n"
  937.         "{ exch dup /FID ne"
  938.         "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n"
  939.         "forall\n");
  940.     if (fontNode->fn_OptFontEncoding == 'S')
  941.         PSIntf("newfont /Encoding encoding put\n");
  942.     PSIntf("/_.100s newfont definefont pop\n", fontNode->fn_TypefaceName);
  943.     /* ... then initmatrix the drawing area and start drawing */
  944.     PSIntf("initmatrix\n");
  945.     PSIntf("/xscale %d %d mul 72 div def\n", newFont->tf_YSize, 72);    /* 72 = optXDen */
  946.     PSIntf("/yscale %d %d mul 72 div def\n", newFont->tf_YSize, 72);    /* 72 = optYDen */
  947.     PSIntf("newfont [ xscale 0 0 yscale 0 0 ] makefont setfont\n");
  948.  
  949.     /* Character loop.  MakeATMChars() keeps a running position ptr and fills */
  950.     /* the CharLoc and CharKern arrays along with the CharData bitmap. */
  951.     /* Since the Amiga uses the position ptrs in tf_CharLoc the chars can */
  952.     /* render in any order. */
  953.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index ++)
  954.     {
  955.         if (fontNode->fn_BuiltChars[index] == CHAR_NEEDED)
  956.         {
  957.             z1 = (fontNode->fn_LowLeftX[index] * fontNode->fn_FontSize * 72 - 41000) / 72000;
  958.             z2 = (fontNode->fn_UpRightX[index] * fontNode->fn_FontSize * 72 + 41000) / 72000;
  959.             zZ = z2 - z1;
  960. //            if (z1 < 0)
  961. //                z1 = 0;
  962.             PSIntf("cstr 0 %d put\n", index);
  963.             PSIntf("%d %d moveto\n", fontNode->fn_ActWidth, fontNode->fn_BaseLine);
  964.             PSIntf(    "gsave %d 0 rlineto 0 %d rlineto "
  965.                 "-%d 0 rlineto closepath clip\n", z2, -fontNode->fn_BaseLine, z2);
  966.             PSIntf("1 setgray fill 0 setgray\n");
  967.             PSIntf("%d %d moveto ", fontNode->fn_ActWidth - z1, fontNode->fn_BaseLine);
  968.             y1 = ((-fontNode->fn_LowLeftY[index]) * fontNode->fn_FontSize * 72) / 72;
  969.             y2 = fontNode->fn_BaseLine * 1000;
  970.             if (y1 > y2)
  971.                 PSIntf("1 %d %d div scale\n", y2, y1);
  972.             PSIntf( "cstr show\n"
  973.                 "grestore\n");
  974.             PSIntf( "gsave %d 0 rlineto 0 %d rlineto "
  975.                 "-%d 0 rlineto closepath clip\n", zZ, fontNode->fn_FontSize - fontNode->fn_BaseLine, zZ);
  976.             /* formerly z2 and z2, used zZ to fix nasty character clipping */
  977.             PSIntf("1 setgray fill newpath 0 setgray\n");
  978.             PSIntf("%d %d moveto ", fontNode->fn_ActWidth - z1, fontNode->fn_BaseLine);
  979.             if (psError != 0)
  980.             {
  981.                 PSTrace("PostScript error drawing character %d %c\n", index, index);
  982.                 break;
  983.             }
  984.             y1 = (fontNode->fn_UpRightY[index] * fontNode->fn_FontSize * 72) / 72;
  985.             y2 = (newFont->tf_YSize - fontNode->fn_BaseLine) * 1000;
  986.             if (y1 > y2)
  987.                 PSIntf("1 %d %d div scale\n", y2, y1);
  988.             PSIntf(    "cstr show\n"
  989.                 "null currentpoint 2 { round cvi exch } repeat "
  990.                 "2 1 callextfunc\n"
  991.                 "grestore\n");
  992. //            fontNode->fn_CharPosX += zZ;
  993.             fontNode->fn_CharLoc[(index - fontNode->fn_LowChar) * 2] = fontNode->fn_ActWidth;
  994.             fontNode->fn_ActWidth += zZ;
  995.             fontNode->fn_BuiltChars[index] = CHAR_DRAWN;
  996.         }
  997.     }
  998.  
  999.     /* I really don't expect any errors here so just return(TRUE). */
  1000.     /* The font already exists and there's enough memory by this point. */
  1001.     return(TRUE);
  1002. }
  1003.  
  1004. /* External function for POST activation */
  1005. __geta4 void SetBBox (int ch, int lx, int ly, int rx, int ry)
  1006. {
  1007.     lowLeftX[ch] = lx;
  1008.     lowLeftY[ch] = ly;
  1009.     upRightX[ch] = rx;
  1010.     upRightY[ch] = ry;
  1011.     return;
  1012. }
  1013.  
  1014. /* External function for POST activation */
  1015. __geta4 void SetCPos(int cpx, int cpy)
  1016. {
  1017.     *charPosX = cpx;
  1018.     *charPosY = cpy;
  1019.     return;
  1020. }
  1021.  
  1022. /* Nice function for PS tracing */
  1023. void PSTrace(char *format, ...)
  1024. {
  1025.     va_list    ap;
  1026.  
  1027.     if (psError != 0)
  1028.         return;
  1029.  
  1030.     if (OPTTRACE)
  1031.     {
  1032.         va_start(ap, format);
  1033.         vfprintf(stdout, format, ap);
  1034.         fflush(stdout);
  1035.         va_end(ap);
  1036.     }
  1037.     return;
  1038. }
  1039.  
  1040. /* Nice function for PS command tracing too */
  1041. void PSIntf(char *format, ...)
  1042. {
  1043.     va_list    ap;
  1044.     char    psString[200];
  1045.  
  1046.     if (psError != 0)
  1047.         return;
  1048.  
  1049.     va_start(ap, format);
  1050.     if (OPTDEBUG)
  1051.     {
  1052.         vfprintf(stdout, format, ap);
  1053.         fflush(stdout);
  1054.     }
  1055.     vsprintf(psString, format, ap);
  1056.     psError = PSintstring(psActivation, psString, -1, PSFLAGSTRING);
  1057.     va_end(ap);
  1058.     return;
  1059. }
  1060.  
  1061. __geta4 __regargs struct TextFont *NewOpenDiskFont(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase)
  1062. {
  1063. struct    DiskfontMsg    *diskFontMsg;
  1064. struct    TextFont    *tempTextFont;
  1065.     BOOL        msgSent;
  1066.     BOOL        atmFont;
  1067.  
  1068.     diskFontMsg = (struct DiskFontMsg *)0x00000000;
  1069.     tempTextFont = (struct TextFont *)0x00000000;
  1070.  
  1071.     diskFontMsg = (struct DiskFontMsg *)AllocVec(sizeof(struct DiskfontMsg), MEMF_PUBLIC | MEMF_CLEAR);
  1072.     if (diskFontMsg != 0)
  1073.     {
  1074.         /* Prepare message for sending */
  1075.         diskFontMsg->df_ATMMsg.atm_MsgLength = sizeof(struct DiskfontMsg);
  1076.         diskFontMsg->df_ATMMsg.atm_DestPort = "ATM_ODF_Port";
  1077.         diskFontMsg->df_TextAttr = textAttr;
  1078.         diskFontMsg->df_TextFont = 0;
  1079.         /* send message */
  1080.         msgSent = ATMSendMsg((struct ATMMessage *)diskFontMsg);
  1081.         atmFont = diskFontMsg->df_ATMFont;
  1082.         tempTextFont = diskFontMsg->df_TextFont;
  1083.         FreeVec(diskFontMsg);
  1084.     }
  1085.     tempTextFont = OldOpenDiskFont(textAttr, libBase);
  1086.     return(tempTextFont);
  1087. }
  1088.  
  1089. __geta4 __regargs void NewText(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase)
  1090. {
  1091. struct    TextMsg        *textMsg;
  1092.     BOOL        msgSent;
  1093.  
  1094.     textMsg = (struct TextMsg *)AllocVec(sizeof(struct TextMsg), (MEMF_PUBLIC | MEMF_CLEAR));
  1095.  
  1096.     if (textMsg != 0)
  1097.     {
  1098.         /* Prepare TextMsg struct for use */
  1099.         textMsg->tm_ATMMsg.atm_DestPort = "ATM_Text_Port";
  1100.         textMsg->tm_ATMMsg.atm_MsgLength = sizeof(struct TextMsg);
  1101.         textMsg->tm_RastPort = rastPort;
  1102.         textMsg->tm_Chars = textString;
  1103.         textMsg->tm_Length = length;
  1104.             /* send the message */
  1105.         msgSent = ATMSendMsg((struct ATMMessage *)textMsg);
  1106.         FreeVec(textMsg);
  1107.     }
  1108.  
  1109.     OldText(rastPort, textString, length, libBase);
  1110.     /* don't forget the gfxBase in A6, or you're toast. */
  1111.     return;
  1112. }
  1113.  
  1114. /* Unlike the previous patches, this patch needs a bit more intelligence.
  1115.    As such, the server will pass back a new TextFont ptr and style bits
  1116.    not yet set (such as FSF_UNDERLINED) so the patch can still set a 
  1117.    software style as required.  This will then SetFont() the font passed
  1118.    back and SetSoftStyle() any missing styles. */
  1119. __geta4 __regargs ULONG NewSSStyle(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase)
  1120. {
  1121. struct    SSStyleMsg    *sssMsg;
  1122.     ULONG        stylesNeeded = newStyle;
  1123.     ULONG        resultingStyle;
  1124. struct    TextFont    *changedFont;
  1125.     BOOL        msgSent;
  1126.  
  1127.     sssMsg = (struct SSStyleMsg *)AllocVec(sizeof(struct SSStyleMsg), (MEMF_PUBLIC | MEMF_CLEAR));
  1128.     if (sssMsg != 0)
  1129.     {
  1130.         /* prepare message struct */
  1131.         sssMsg->ss_ATMMsg.atm_DestPort = "ATM_SSS_Port";
  1132.         sssMsg->ss_ATMMsg.atm_MsgLength = sizeof(struct SSStyleMsg);
  1133.         sssMsg->ss_RastPort = rastPort;
  1134.         sssMsg->ss_NewStyle = newStyle;
  1135.         sssMsg->ss_Enable = enable;
  1136.         sssMsg->ss_SoftStyleNeeded = newStyle;
  1137.         /* Send the message */
  1138.         msgSent = ATMSendMsg((struct ATMMessage *)sssMsg);
  1139.         /* Check for successful style changes and change the font as needed */
  1140.         changedFont = sssMsg->ss_ChangedFont;
  1141.         stylesNeeded = sssMsg->ss_SoftStyleNeeded;
  1142.         if (changedFont != 0)
  1143.         {
  1144.             OpenFont(changedFont);
  1145.             SetFont(rastPort, changedFont);
  1146.         }
  1147.         FreeVec(sssMsg);
  1148.     }
  1149.  
  1150.     /* Call original function to complete any needed style change */
  1151.     resultingStyle = OldSSStyle(rastPort, stylesNeeded, enable, libBase);
  1152.     return(resultingStyle);
  1153. }
  1154.  
  1155. /* Message sender.  This guys gets a lot of working out! */
  1156. __geta4 BOOL ATMSendMsg(struct ATMMessage *atmMsg)
  1157. {
  1158. struct    MsgPort        *msgPort, *replyPort;
  1159. struct    Message        *replyMsg;
  1160.     ULONG        portSig;
  1161.  
  1162. /* generate reply port */
  1163.     replyPort = CreateMsgPort();
  1164.     if (replyPort == 0)
  1165.         return(FALSE);
  1166.     
  1167. /* Reply port set up.  Now build the message. */
  1168.     atmMsg->atm_Message.mn_Length = atmMsg->atm_MsgLength;
  1169.     atmMsg->atm_Message.mn_ReplyPort = replyPort;
  1170.  
  1171. /* OK we have a valid reply port and a message.  Time to send it. */
  1172.     portSig = 1 << replyPort->mp_SigBit;
  1173.     Forbid();
  1174.     msgPort = FindPort(atmMsg->atm_DestPort);
  1175.     if (msgPort)
  1176.         PutMsg(msgPort,(struct Message *)atmMsg);
  1177.     Permit();
  1178.     if (msgPort)
  1179.     {
  1180.         Wait(portSig);
  1181.         replyMsg=GetMsg(replyPort);
  1182.     }
  1183.  
  1184. /* So, sent the message.  Now free the port & exit */
  1185.     DeleteMsgPort(replyPort);
  1186.     if ((msgPort != 0) && (replyMsg != 0))
  1187.         return(TRUE);
  1188.     else
  1189.         return(FALSE);
  1190. }
  1191.